/** @brief Define the transaction class.
 *
 *  transaction.h
 *  kangmodb
 *
 *  Created by 강모 김 on 11. 4. 24..
 *  Copyright 2011 강모소프트. All rights reserved.
 *
 */

#ifndef _KD_TRANSACTION_H_
#define _KD_TRANSACTION_H_ (1)

#include "kdInfra.h"
#include "types.h"
#include "transLogBuffer.h"

/** @brief The tranasction object that has context of reading and modifying records in tables. 
 */
class stgTransaction
{	
private :
	/** @brief The log buffer that keeps all history of modifications done by the transaction 
	 * Upon commit : 1) For each new version records in in-memory data structure, 
     *                  set the version to the commit version allocated from transaction manager.
	 *               2) Append the content of the log buffer to the log stream.
	 * Upon rollback : 1) Eliminate the new version records from the in-memory data structure.
	 *                 2) Simply discard the content of the log buffer without writing it to the log stream.
	 */
	stgTransactionLogBuffer logBuffer_;
	/** The maximum version that this transaction can read. 
	 *  This transaction can't view records whose versions are greater than the viewVersion_. 
	 */ 
	stgVersion viewVersion_;
	/** @brief The version that a committing transaction allocated from transaction manager.
	 *  All records touched by this transaction will have this version by the time the transaction commits. 
	 */
	stgVersion committingVersion_;
	
	/** @brief 
	 */
	stgSavepointId nextSavepointId;
public :
	stgTransaction() : viewVersion_(STG_VERSION_NULL), committingVersion_(STG_VERSION_NULL) 
	{
		reset();
	}

	/** @brief Reset the transaction object so that it can be reused 
	 */
	KD_VOID reset() 
	{
		KD_TRY
		{
			// BUGBUG change to an error code.
			// If this assert hits, it means allocCommittingVersion was called but commitVersion or revertVersion was not called.
			KD_ASSERT( committingVersion_ == STG_VERSION_NULL );
		
			// BUGBUG change to an error code.
			// Log should have been truncated either by rollback or commit.
			KD_ASSERT( logBuffer_.empty() );

			// Reset maxReadVersion_
			setViewVersion( STG_VERSION_NULL );

			// Reset the next savepoint ID to use.
			nextSavepointId = 1;
		}
		KD_CATCH
		KD_FINALLY
		KD_END
	}

	/** @brief Allocate a new savepoint. Savepoint is an integer starting from 1, increasing monotonously 
	 */
	KD_VOID allocSavepoint(stgSavepointId * savepointId)
	{
		KD_TRY
		{
			// TODO : Implement
			KD_ASSERT(0);
		}
		KD_CATCH
		KD_FINALLY
		KD_END
	}

	/** @brief Revert new versions created after the savepoint was allocated.
	 */
	KD_VOID revertNewVersionsSince(const stgSavepointId savepoint)
	{
		KD_TRY
		{
			// TODO : Implement
			KD_ASSERT(0);
		}
		KD_CATCH
		KD_FINALLY
		KD_END
	}

	/** @brief Truncate log records after the savepoint was allocated. 
	 */
	KD_VOID truncateLogSince(const stgSavepointId savepoint)
	{
		KD_TRY
		{
			// TODO : Implement
			KD_ASSERT(0);
		}
		KD_CATCH
		KD_FINALLY
		KD_END
	}

	/** @brief Update the version of touched records by this transaction to committingVersion_ 
	 */
	KD_VOID updateCommitVersion()
	{
		KD_TRY
		{
			// TODO : Implement
			KD_ASSERT(0);
		}
		KD_CATCH
		KD_FINALLY
		KD_END
	}
	
	/** @brief Setter for viewVersion_
	 */
	KD_INLINE void setViewVersion(const stgVersion viewVersion)
	{
		viewVersion_ = viewVersion;
	} 

	/** @brief Getter for viewVersion_
	 */
	KD_INLINE const stgVersion getViewVersion() const 
	{
		return viewVersion_;
	}

	/** @brief Setter for committingVersion_
	 */
	KD_INLINE void setCommittingVersion( const stgVersion committingVersion) 
	{
		committingVersion_ = committingVersion;
	}

	/** @brief Getter for committingVersion_
	 */
	KD_INLINE const stgVersion getCommittingVersion() const 
	{
		return committingVersion_;
	}
	
	/** @brief Getter for logBuffer_
	 */
	KD_INLINE const stgTransactionLogBuffer & getLogBuffer() const 
	{
		return logBuffer_;
	}
};

#endif /*_KD_TRANSACTION_H_ */